/*
 * =====================================================================================
 *
 *       Filename:  timer.c
 *
 *    Description:  
 *
 *        Version:  1.0
 *        Created:  2025/03/16 21时38分59秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  zhuzonghui(puchuchen@outlook.com) (), 
 *   Organization:  
 *
 * =====================================================================================
 */
#include <fuquOS/timer.h>
#include <fuquOS/pit.h>
#include <fuquOS/io.h>
#include <fuquOS/memory.h>

void sleep_ticks(u32 ticks_to_wait){
    u32 end=get_tick_count()+ticks_to_wait;
    while(get_tick_count()<end){
        asm volatile("hlt");
    }
}

u8 read_cmos(u8 reg){
    outb(CMOS_ADDRESS,reg);
    return inb(CMOS_DATA);
}

int bcd_to_int(u8 bcd){
    return (bcd &0x0F)+((bcd>>4)*10);
}

Time* get_utc_time(){
    Time *time=(Time *)kmalloc(sizeof(Time));
    time->sec=bcd_to_int(read_cmos(CMOS_REG_SEC));
    time->min=bcd_to_int(read_cmos(CMOS_REG_MIN));
    time->hour=bcd_to_int(read_cmos(CMOS_REG_HOUR));
    time->day=bcd_to_int(read_cmos(CMOS_REG_DAY));
    time->month=bcd_to_int(read_cmos(CMOS_REG_MON));
    time->year=bcd_to_int(read_cmos(CMOS_REG_YEAR));

    int century=read_cmos(CMOS_REG_CENT);
    if(century){
        time->year+=bcd_to_int(century)*100;
    }else{
        time->year+=2000;
    }
    return time;
}

Time* get_beijing_time(){
    Time *time=get_utc_time();
    time->hour+=8;

    int max_day=days_in_month[time->month-1];
    if(time->month==2&&is_leap_year(time->year)){
        max_day=29;
    }

    if(time->hour>=24){
        time->hour-=24;
        time->day+=1;
    }

    if(time->day>=max_day){
        time->day=1;
        time->month++;
    }

    if(time->month>12){
        time->month=1;
        time->year++;
    }

    return time;
}

int is_leap_year(int year){
    return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}

